package sc.math;

import java.util.ArrayList;
import java.util.List;

public final class Spline2D {

	// Control points
    public List<double[]> points;
    
    private CubicCurve cubiccurve;
    private int start;
    private int end;
    private int step;

    /** Constructs a Spline2D using the specified CubicCurve */
    public Spline2D(CubicCurve cubiccurve) {
        points = new ArrayList<double[]>();
        this.cubiccurve = cubiccurve;
        start = cubiccurve.startIndex();
        end = cubiccurve.endIndex();
        step = end - start;
    }
    
    /**
     * Gets index of control point within d distance from x, y; else -1
     *
     * @param x
     * 			x-coordinate
     * @param y
     * 			y-coordinate
     * @param dist
     * 			Threshold of distance away from point
     */
	public int near(double x, double y, int dist) {
		int index = 0;
		
		for (double[] p : points) {
			double proximity = Math.sqrt((x - p[0]) + (y - p[1]));
			if (proximity <= dist)
				return index;
			index++;
		}
		
		return -1;
	}

    /**
     * Gets the intervals of the curve.
     * 
     * @param interval
     * 			Number of intervals between control points
     * 
     * @return List of intervals
     */
    public List<double[]> intervals(double interval) {
    	List<double[]> intervals = new ArrayList<double[]>();
    	double[][] p = new double[4][2];
    	double n = 0;
    	
    	// Doesn't work if there are not enough control points 
        if (points.size() < 4) {
            return intervals;
        }
        
        // Convert specified interval to a fraction
        interval = 1f / interval;

        for (int t = start; t < points.size() - (4 - start - 1); t += step) {
            p[0] = points.get(t - start);
            p[1] = points.get(t - start + 1);
            p[2] = points.get(t - start + 2);
            p[3] = points.get(t - start + 3);

            for (; n < 1; n += interval) {
            	double[] z = new double[2];
                z[0] = cubiccurve.interval(p[0][0], p[1][0], p[2][0], p[3][0], n);
                z[1] = cubiccurve.interval(p[0][1], p[1][1], p[2][1], p[3][1], n);
                intervals.add(z);
            }

            n -= 1;
        }
        
        return intervals;
    }
}
